package com.mangix.http;

import com.mangix.files.MangixFiles;

import javax.servlet.AsyncContext;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * Created by Ahan on 2014/8/16.A
 */
public class MangixDirectObjectReadListener implements ReadListener {
    private ServletInputStream input;
    private AsyncContext context;
    private Path file;
    private Path tempFile;
    private OutputStream out;
    private MangixFiles mangixFiles;
    private int replicasNum;
    private byte[] buffer;

    public MangixDirectObjectReadListener(ServletInputStream input, AsyncContext context, Path file, MangixFiles mangixFiles, int replicasNum) {
        this.input = input;
        this.context = context;
        this.file = file;
        this.mangixFiles = mangixFiles;
        this.replicasNum = replicasNum;
    }

    @Override
    public void onDataAvailable() throws IOException {
        // Create the temp file.
        if (tempFile == null) {
            UUID uuid = UUID.randomUUID();
            this.buffer = new byte[1024];
            tempFile = Paths.get(file.getParent().toString(), uuid + ".tmp");
            // Create a temporary file.
            out = mangixFiles.getOutputStream(tempFile);
        }
        int len;
        while (input.isReady() && (len = input.read(buffer)) != -1) {
            out.write(buffer, 0, len);
        }
    }

    @Override
    public void onAllDataRead() throws IOException {
        if (out != null) {
            out.close();
        }
        // Write the meta data of the object to the file.
        mangixFiles.setReplicasNum(tempFile, replicasNum);
        Files.move(tempFile, file);
        input.close();
        HttpServletResponse resp = (HttpServletResponse)context.getResponse();
        resp.getOutputStream().close();
        context.complete();
        System.out.format("Update object: %s%n", file.toString());
    }

    @Override
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
        if (out != null) {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            Files.deleteIfExists(tempFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        HttpServletResponse resp = (HttpServletResponse)context.getResponse();
        try {
            resp.getOutputStream().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        context.complete();
    }
}
